// 贿赂怪兽
// 开始时你的能力是0，你的目标是从0号怪兽开始，通过所有的n只怪兽
// 如果你当前的能力小于i号怪兽的能力，则必须付出b[i]的钱贿赂这个怪兽
// 然后怪兽就会加入你，他的能力a[i]直接累加到你的能力上
// 如果你当前的能力大于等于i号怪兽的能力，你可以选择直接通过，且能力不会下降
// 但你依然可以选择贿赂这个怪兽，然后怪兽的能力直接累加到你的能力上
// 返回通过所有的怪兽，需要花的最小钱数
// 测试链接 : https://www.nowcoder.com/practice/736e12861f9746ab8ae064d4aae2d5a9
// 提交以下的code，可以直接通过

#include <bits/stdc++.h>

using namespace std;

inline int read()
{
    char ch = getchar();
    int x = 0, f = 1;
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = 10 * x + ch - '0';
        ch = getchar();
    }
    return f * x;
}

// 讲解本题的目的不仅仅是为了通过这个题，而是进行如下的思考:
// 假设a[i]数值的范围很大，但是b[i]数值的范围不大，该怎么做？
// 假设a[i]数值的范围不大，但是b[i]数值的范围很大，又该怎么做？
// a[i] : 怪兽的力量，b[i] : 怪兽需要的金钱

// 假设a[i]数值的范围很大，但是b[i]数值的范围不大
// 时间复杂度O(n * 所有怪兽的钱数累加和)
int compute1(int n, int* a, int* b)
{
    int m = 0;
    // 算出金钱的总数
    for(int i = 1; i <= n; ++i) m += b[i];

    // dp[i][j] : 花的钱不能超过j，通过前i个怪兽，最大能力是多少
    // 如果dp[i][j] == INT_MIN，表示花的钱不能超过j，无论如何都无法通过前i个怪兽
    int dp[n + 1][m + 1];
    memset(dp, 0, sizeof dp);
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 0; j <= m; ++j) // j 是金钱
        {
            dp[i][j] = INT_MIN;
            if(dp[i - 1][j] >= a[i]) // 不贿赂
            {
                dp[i][j] = dp[i - 1][j];
            }
            if(j - b[i] >= 0 && dp[i - 1][j - b[i]] != INT_MIN) // 贿赂
            {
                dp[i][j] = max(dp[i][j], dp[i - 1][j - b[i]] + a[i]);
            }
        }
    }

    int ans = -1;
    for(int j = 0; j <= m; ++j)
    {
        if(dp[n][j] != INT_MIN)
        {
            ans = j;
            break;
        }
    }
    return ans;
}

// 就是方法1的空间压缩版本
int compute2(int n, int* a, int* b)
{
    int m = 0;
    for(int i = 1; i <= n; ++i) m += b[i];

    int dp[m + 1];
    memset(dp, 0, sizeof dp);
    for(int i = 1, cur; i <= n; ++i)
    {
        for(int j = m; j >= 0; --j) // j 是金钱
        {
            cur = INT_MIN;
            if(dp[j] >= a[i]) // 不贿赂
            {
                cur = dp[j];
            }
            if(j - b[i] >= 0 && dp[j - b[i]] != INT_MIN) // 贿赂
            {
                cur = max(cur, dp[j - b[i]] + a[i]);
            }
            dp[j] = cur;
        }
    }
    
    int ans = -1;
    for(int j = 0; j <= m; ++j)
    {
        if(dp[j] != INT_MIN)
        {
            ans = j;
            break;
        }
    }
    return ans;
}

// 假设a[i]数值的范围不大，但是b[i]数值的范围很大
// 时间复杂度O(n * 所有怪兽的能力累加和)
int compute3(int n, int* a, int* b)
{
    int m = 0;
    // 算出能力的总数
    for(int i = 1; i <= n; ++i) m += a[i];

    const int INF = 0x3f3f3f3f;
    int dp[n + 1][m + 1];
    // dp[i][j] : 能力正好是j，并且确保能通过前i个怪兽，至少需要花多少钱
    // 如果dp[i][j] == INF，表示能力正好是j，无论如何都无法通过前i个怪兽
    memset(dp, 0x3f, sizeof dp);
    dp[0][0] = 0;
    // 无法获得 j 的能力，因此设置为 INF
    // for(int j = 1; j <= m; ++j) dp[0][j] = INF; 
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 0; j <= m; ++j) // j 是能力
        {
            // dp[i][j] = INF;
            if(j >= a[i] && dp[i - 1][j] != INF) // 不贿赂
            {
                dp[i][j] = dp[i - 1][j];
            }
            if(j >= a[i] && dp[i - 1][j - a[i]] != INF) // 贿赂
            {
                dp[i][j] = min(dp[i][j], dp[i - 1][j - a[i]] + b[i]);
            }
        }
    }

    int ans = INF;
    for(int j = 0; j <= m; ++j)
    {
        ans = min(ans, dp[n][j]);
    }
    return ans == INF ? -1 : ans;
}

// 就是方法3的空间压缩版本
int compute4(int n, int* a, int* b)
{
    int m = 0;
    for(int i = 1; i <= n; ++i) m += a[i];

    const int INF = 0x3f3f3f3f;
    int dp[m + 1];
    memset(dp, 0x3f, sizeof dp);
    dp[0] = 0;
    for(int i = 1, cur; i <= n; ++i)
    {
        for(int j = m; j >= 0; --j) // j 是能力
        {
            cur = INF;
            if(j >= a[i] && dp[j] != INF) // 不贿赂
            {
                cur = dp[j];
            }
            if(j >= a[i] && dp[j - a[i]] != INF) // 贿赂
            {
                cur = min(cur, dp[j - a[i]] + b[i]);
            }
            dp[j] = cur;
        }
    }

    int ans = INF;
    for(int j = 0; j <= m; ++j)
    {
        ans = min(ans, dp[j]);
    }
    return ans == INF ? -1 : ans;
}

int main()
{
    int n = read();
    int a[n + 1], b[n + 1];
    for(int i = 1; i <= n; ++i)
    {
        a[i] = read();
        b[i] = read();
    }
    printf("%d\n", compute2(n, a, b));

    return 0;    
}